using System;
using System.Collections.Generic;
using System.Xml;

namespace BasecampRestAPI
{
	/*
	<todo-item>
	  <id type="integer">#{id}</id>
	  <content>#{content}</content>
	  <position type="integer">#{position}</position>
	  <created-on type="datetime">#{created_on}</created-on>
	  <creator-id type="integer">#{creator_id}</creator-id>
	  <completed type="boolean">#{completed}</completed>
	  <comments-count type="integer">#{comments_count}</comments-count>

	  <!-- if the item has a responsible party -->
	  <responsible-party-type>#{responsible_party_type}</responsible-party-type>
	  <responsible-party-id type="integer">#{responsible_party_id}</responsible-party-id>

	  <!-- if the item has been completed -->
	  <completed-on type="datetime">#{completed_on}</completed-on>
	  <completer-id type="integer">#{completer_id}</completer-id>
	</todo-item>
	 */
	public class ToDoListItem : IToDoListItem
	{
		private readonly IBaseCamp _camp;
		private readonly int _creatorId;
		private readonly int _responsiblePartyId;
		private readonly int _completerId;
		private IPerson _completer;
		private IPerson _responsibleParty;
		private IPerson _creator;
		private readonly IRestWebService _service;

		public static IToDoListItem GetInstance(IBaseCamp camp, XmlNode node)
		{
			return new ToDoListItem(camp, camp.Service, node);
		}
		private ToDoListItem(IBaseCamp camp, IRestWebService service, XmlNode node)
		{
			_camp = camp;
			_service = service;
			Id = XmlHelpers.ParseInteger(node, "id");
			Content = XmlHelpers.ChildNodeText(node, "content");
			Position = XmlHelpers.ParseInteger(node, "position");
			CreatedOn = XmlHelpers.ParseDateTime(node, "created-on");
			_creatorId = XmlHelpers.ParseInteger(node, "creator-id");
			Completed = XmlHelpers.ParseBool(node, "completed");
			CommentsCount = XmlHelpers.ParseInteger(node, "comments-count");
			if (node.SelectSingleNode("responsible-party-type") != null)
			{
				ResponsiblePartyType = XmlHelpers.ChildNodeText(node, "responsible-party-type");
				_responsiblePartyId = XmlHelpers.ParseInteger(node, "responsible-party-id");
			}
			else
			{
				ResponsiblePartyType = string.Empty;
				_responsiblePartyId = -1;
			}
			if (Completed)
			{
				CompletedOn = XmlHelpers.ParseDateTime(node, "completed-on", DateTime.MinValue);
				_completerId = XmlHelpers.ParseInteger(node, "completer-id");
			}
			else
			{
				CompletedOn = DateTime.MinValue;
				_completerId = -1;
			}
		}

		#region Implementation of IToDoListItem

		public int Id { get; private set; }
		public string Content { get; set; }
		public int Position { get; private set; }
		public DateTime CreatedOn { get; private set; }
		public IPerson Creator
		{
			get
			{
				if (_creator == null)
				{
					_creator = _camp.GetPersonById(_creatorId);
				}
				return _creator;
			}
		}
		public bool Completed { get; set; }
		public int CommentsCount { get; private set; }
		public string ResponsiblePartyType { get; set; }

		public IPerson ResponsibleParty
		{
			get
			{
				if (_responsibleParty == null && _responsiblePartyId != -1)
				{
					_responsibleParty = _camp.GetPersonById(_responsiblePartyId);
				}
				return _responsibleParty;
			}
			set
			{
				_responsibleParty = value;
			}
		}

		public DateTime CompletedOn { get; set; }
		public IPerson Completer
		{
			get
			{
				if (_completer == null && _completerId != -1)
				{
					_completer = _camp.GetPersonById(_completerId);
				}
				return _completer;
			}
			set { _completer = value; }
		}

		public IComment AddComment(string body)
		{
			string requestPath = PathForAction("comments.xml");
			string data = string.Format(Properties.Resources.AddComment, XmlHelpers.EscapeXml(body));
			string location = _camp.Service.PostRequestGetLocation(requestPath, data);
			return Comment.GetInstance(_camp, _service.GetRequestResponseElement(location));
		}

		public ITimeEntry AddTimeEntry(IPerson person, DateTime date, double hours, string description)
		{
			string requestPath = PathForAction("time_entries.xml");
			string data = string.Format(Properties.Resources.AddTimeEntryRequest,
				person.Id, XmlHelpers.DateString(date), hours, XmlHelpers.EscapeXml(description), Id);
			string location = _camp.Service.PostRequestGetLocation(requestPath, data);
			return TimeEntry.GetInstance(_camp, _service.GetRequestResponseElement(location));
		}

		public ITimeEntry[] TimeEntries
		{
			get
			{
				string requestPath = PathForAction("time_entries.xml");
				List<ITimeEntry> entries = new List<ITimeEntry>();
				foreach (XmlNode node in _service.GetRequestResponseElement(requestPath).ChildNodes)
				{
					entries.Add(TimeEntry.GetInstance(_camp, node));
				}
				return entries.ToArray();
			}
		}

		public void Complete()
		{
			_camp.Service.PutRequest(PathForAction("complete.xml"), string.Empty);
		}

		private string PathForAction(string actionPath)
		{
			return string.Format("todo_items/{0}/{1}", Id, actionPath);
		}

		public IComment[] RecentComments
		{
			get { return _camp.CommentsForResource("todo_items", Id); }
		}

		#endregion
	}
}